home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_usrdoc / SVGALIB-.{2E / ET4000 / TSENG3.C < prev    next >
C/C++ Source or Header  |  1999-09-17  |  19KB  |  646 lines

  1. /*
  2. **  tseng3.c - get ET4000 graphics register values
  3. **  Copyright (C) 1993  Tommy Frandsen, Harm Hanemaayer, Hartmut Schirmer
  4. **
  5. **  This program is free software;
  6. **
  7. **  Permission is granted to any individual or institution to use, copy,
  8. **  or redistribute this executable so long as it is not modified and
  9. **  that it is not sold for profit.
  10. **
  11. **  LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND
  12. **  COMEs WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
  13. **  IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES
  14. **  RESULTING FROM THE USE OF THIS SOFTWARE.
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <conio.h>
  21. #include <dos.h>
  22. #include <stdarg.h>
  23.  
  24. /* VGA index register ports */
  25. #define CRT_I   0x3D4   /* CRT Controller Index (mono: 0x3B4) */
  26. #define ATT_IW  0x3C0   /* Attribute Controller Index & Data Write Register */
  27. #define GRA_I   0x3CE   /* Graphics Controller Index */
  28. #define SEQ_I   0x3C4   /* Sequencer Index */
  29. #define PEL_IW  0x3C8   /* PEL Write Index */
  30.  
  31. /* VGA data register ports */
  32. #define CRT_D   0x3D5   /* CRT Controller Data Register (mono: 0x3B5) */
  33. #define ATT_R   0x3C1   /* Attribute Controller Data Read Register */
  34. #define GRA_D   0x3CF   /* Graphics Controller Data Register */
  35. #define SEQ_D   0x3C5   /* Sequencer Data Register */
  36. #define MIS_R   0x3CC   /* Misc Output Read Register */
  37. #define MIS_W   0x3C2   /* Misc Output Write Register */
  38. #define IS1_R   0x3DA   /* Input Status Register 1 (mono: 0x3BA) */
  39. #define PEL_D   0x3C9   /* PEL Data Register */
  40.  
  41. /* VGA indexes max counts */
  42. #define CRT_C   24              /* 24 CRT Controller Registers */
  43. #define ATT_C   21              /* 21 Attribute Controller Registers */
  44. #define GRA_C   9               /* 9  Graphics Controller Registers */
  45. #define SEQ_C   5               /* 5  Sequencer Registers */
  46. #define MIS_C   1               /* 1  Misc Output Register */
  47. #define EXT_C    17        /* 11 SVGA Extended Registers */
  48.  
  49. /* VGA registers saving indexes */
  50. #define CRT     0               /* CRT Controller Registers start */
  51. #define ATT     CRT+CRT_C       /* Attribute Controller Registers start */
  52. #define GRA     ATT+ATT_C       /* Graphics Controller Registers start */
  53. #define SEQ     GRA+GRA_C       /* Sequencer Registers */
  54. #define MIS     SEQ+SEQ_C       /* General Registers */
  55. #define EXT     MIS+MIS_C       /* SVGA Extended Registers */
  56. #define TOTAL    EXT+EXT_C    /* # or registers values */
  57.  
  58. unsigned char vga_regs[TOTAL];
  59. static int do_all = 0;
  60. FILE *output = NULL;
  61.  
  62. static int save_extregs;
  63.  
  64. void port_out(unsigned char value, unsigned short port)
  65. {
  66.    asm mov dx,port
  67.    asm mov al,value
  68.    asm out dx,al
  69. }
  70.  
  71.  
  72. unsigned char port_in(unsigned short port)
  73. {
  74.     asm mov dx,port
  75.     asm in al,dx
  76.     return (_AL);
  77. }
  78.  
  79. int dactype(void)
  80. {
  81.     union REGS cpu_regs;
  82.  
  83.     cpu_regs.x.ax=0x10F1;
  84.     cpu_regs.x.bx=0x2EFF;
  85.  
  86.     int86(0x10, &cpu_regs, &cpu_regs);
  87.     if (cpu_regs.x.ax != 0x0010)
  88.         return (-1);
  89.     else
  90.         return (cpu_regs.h.bl);
  91. }
  92.  
  93. int read_dac(int addr)
  94. {
  95.     inp(0x3c8);
  96.     inp(0x3c6);
  97.         inp(0x3c6);
  98.         inp(0x3c6);
  99.         inp(0x3c6);
  100.         while (addr)
  101.                 --addr,inp(0x3c6);
  102.         addr = inp(0x3c6);
  103.         return addr;
  104. }
  105.  
  106. int write_dac(int addr,int value)
  107. {
  108.     inp(0x3c8);
  109.     inp(0x3c6);
  110.         inp(0x3c6);
  111.         inp(0x3c6);
  112.         inp(0x3c6);
  113.     while (addr)
  114.         --addr,inp(0x3c6);
  115.         outp(0x3c6,value);
  116.     return read_dac(addr);
  117. }
  118.  
  119. int read_ext_dac(int addr)
  120. {
  121.     write_dac(1,addr);
  122.     write_dac(2,0);
  123.     return read_dac(3);
  124. }
  125.  
  126. void puts2(char *s) {
  127.   if (output != NULL)
  128.     fprintf(output, "%s\n", s);
  129.   while (*s != '\0') {
  130.     if (*s == '\n') putch('\r');
  131.     putch (*(s++));
  132.   }
  133.   putch('\r'); putch('\n');
  134. }
  135.  
  136. int printf2(char *fmt, ...)
  137. {
  138.   va_list  argptr;
  139.   char str[140], *s;
  140.   int cnt;
  141.  
  142.   va_start( argptr, fmt );
  143.  
  144.   if (output != NULL)
  145.     vfprintf(output, fmt, argptr);
  146.   cnt = vsprintf( str, fmt, argptr );
  147.   s = str;
  148.   while (*s) {
  149.     switch (*s) {
  150.       case '\n' : putch('\r');
  151.           break;
  152.       case '\t' : cprintf("%*s", 8-((wherex()-1)&7), "");
  153.           ++s;
  154.           continue;
  155.     }
  156.     putch(*(s++));
  157.   }
  158.   va_end( argptr );
  159.   return( cnt );
  160. }
  161.  
  162. void get_dac(void)
  163. {
  164.     int dac;
  165.  
  166.     dac = dactype();
  167.     switch (dac)
  168.     {
  169.     case -1:
  170.         printf2 ("/* Dac detection BIOS call returned an error */\n");
  171.         break;
  172.     case 0:
  173.         printf2 ("/* Standard VGA dac detected */\n");
  174.         printf2 ("#define DAC_TYPE 0\n");
  175.         break;
  176.     case 1:
  177.         printf2 ("/* Sierra SC1148x HiColor dac detected */\n");
  178.         printf2 ("#define DAC_TYPE 1\n");
  179.         break;
  180.     case 2:
  181.         printf2 ("/* Diamond Speedstar 24 24bit dac or Sierra Mark2/Mark3 dac detected */\n");
  182.         break;
  183.     case 3:
  184.         printf2 ("/* AT&T ATT20c491/2 15/16/24 bit dac detected */\n");
  185.         printf2 ("#define DAC_TYPE 9\n");
  186.         break;
  187.     case 4:
  188.         printf2 ("/* AcuMos ADAC1 15/16/24 bit dac detected */\n");
  189.         break;
  190.     case 8:
  191.         printf2 ("/* Music 15/16/24 bit dac (AT&T compatible) detected */\n");
  192.         printf2 ("#define DAC_TYPE 9\n");
  193.         break;
  194.     default: {    /* use alternate method */
  195.         int cmd = read_dac(0);
  196.         write_dac(0,cmd | 0x10);
  197.         if (read_ext_dac(0) == 0x44) {
  198.             printf2 ("/* SGS-Thomson STG170x 15/16/24 dac detected */\n");
  199.             save_extregs = 1;
  200.         }
  201.         else
  202.             printf2 ("/* Unknown HiColor dac (%d) detected */\n", dac);
  203.         break;
  204.     }
  205.     }
  206. }
  207.  
  208. #define TickTime (1.0/1193182.0)
  209.  
  210. #define init_timer() do { \
  211.   asm mov al, 034h;       \
  212.   asm out 043h, al;       \
  213.   asm xor al, al;         \
  214.   asm out 040h, al;       \
  215.   asm out 040h, al;       \
  216. } while(0)
  217.  
  218. #define ReadTimer(dst) do { \
  219.        asm { mov   al, 4;   \
  220.          out   43h, al; \
  221.          in    al, 40h; \
  222.          mov   bl, al;  \
  223.          in    al, 40h; \
  224.          mov   ah, al;  \
  225.          mov   al, bl;  \
  226.          not   ax     } \
  227.       (dst) = _AX;        \
  228.     } while (0);
  229.  
  230. #define _wait_(ID,VAL)  \
  231. w_##ID##1:              \
  232.   asm in    al, dx;     \
  233.   asm test  al, VAL;    \
  234.   asm jne   w_##ID##1;  \
  235. w_##ID##2:              \
  236.   asm in    al, dx;     \
  237.   asm test  al, VAL;    \
  238.   asm je    w_##ID##2
  239.  
  240. #define wait_horizontal(ID,port)  do { _DX=(port); _wait_(ID##ch,8);} while(0)
  241. #define wait_vertical(ID,port)    do { _DX=(port); _wait_(ID##cv,1);} while(0)
  242. #define __loop__(ID,port,loops,msk)     do { \
  243.         register int cnt = (loops);  \
  244.         _DX=(port);                  \
  245.         do {                         \
  246.           _wait_(ID,msk);            \
  247.         } while (--cnt > 0);         \
  248.     } while(0)
  249. #define loop_vertical(ID,port,loops)    __loop__(ID##cv,(port),(loops),1)
  250.  
  251.  
  252. int interlaced(void) {
  253.   return (vga_regs[EXT+5] & 0x80) ? 1 : 0;
  254. }
  255.  
  256. int calc_vtotal(void) {
  257.   int total;
  258.  
  259.   total = (vga_regs[EXT+5]&2) ? 1024 : 0;
  260.   switch (vga_regs[CRT+7]&0x21) {
  261.     case 0x01 : total += 256; break;
  262.     case 0x20 : total += 512; break;
  263.     case 0x21 : total += 768; break;
  264.   }
  265.   total += vga_regs[CRT+6];
  266.   return total + 2;
  267. }
  268.  
  269. double measure_horizontal(void)
  270. {
  271.   short start, stop;
  272.   long  diff;
  273.  
  274.   disable();
  275.   init_timer();
  276.   wait_horizontal(mv0,0x3da);
  277.   wait_vertical(mv0,0x3da);
  278.   ReadTimer(start);
  279.   loop_vertical(mv, 0x3da, 200);
  280.   ReadTimer(stop);
  281.   enable();
  282.   diff = stop-start;
  283.   if (diff < 0) diff += 65536L;
  284.   return 200/(TickTime*((double)diff));
  285. }
  286.  
  287. #define ASK_CONT 0
  288. #define ASK_SKIP 1
  289. #define ASK_ALL  2
  290.  
  291. int ask(char *expl)
  292. {
  293.     int ch;
  294.  
  295.     cprintf("\r\n\n"
  296.         "╔════════════════════════════════════════════════════════════════╗\r\n"
  297.         "║ WARNING: Improper use of this program may destroy your monitor ║\r\n"
  298.         "╚════════════════════════════════════════════════════════════════╝\r\n\n"
  299.         "%s\r\n\n"
  300.         "Type SPACE to skip, ESC to cancel program, RETURN to continue ... ",
  301.         expl);
  302.     do {
  303.       ch = getch();
  304.       if (ch == 27) exit(1);
  305.       switch (ch) {
  306.     case 27  : exit(1);
  307.     case ' ' : return ASK_SKIP;
  308.     case 'A' : return ASK_ALL;
  309.     case '\r': return ASK_CONT;
  310.       }
  311.     } while (1);
  312. }
  313.  
  314.  
  315. void get_clocks(void)
  316. {
  317.     union REGS cpu_regs;
  318.     unsigned char temp;
  319.     int i;
  320.     double clock[8], horzbase, baseosc;
  321.  
  322.     if (!do_all)
  323.       switch (ask("Measure clock frequencies")) {
  324.     case ASK_SKIP : return;
  325.     case ASK_ALL  : do_all = 1; break;
  326.     default       : break;
  327.       }
  328.  
  329.     cpu_regs.h.ah = 0x00;
  330.     cpu_regs.h.al = 0x13;
  331.     int86(0x10, &cpu_regs, &cpu_regs);
  332.     port_out(0x03, 0x3BF);  /* Unprotect ET4000 registers */
  333.     port_out(0xA0, 0x3D8);
  334.     port_out(0x00, ATT_IW); /* disable video */
  335.     port_out(7, SEQ_I);     /* devide by 4 */
  336.     temp = port_in(SEQ_D);
  337.     port_out(temp | 0x41, SEQ_D);
  338.  
  339.     baseosc = 25175;        /* Base frequency */
  340.     switch (temp & 0x41) {
  341.       case 0x41 : baseosc *= 4; break;
  342.       case 0x40 : baseosc *= 2; break;
  343.     }
  344.     clock[0] = baseosc;
  345.     clock[1] = baseosc * 28322.0 / 25175.0;
  346.     horzbase = measure_horizontal();
  347.     for (i=2; i < 8; ++i) {
  348.       temp = (port_in(MIS_R) & 0xF3) | ((i&3)<<2);
  349.       port_out(temp, MIS_W);
  350.       port_out(0x34, CRT_I);
  351.       temp = (port_in(CRT_D) & 0xFD) | ((i&4)>>1);
  352.       port_out(temp, CRT_D);
  353.       clock[i] = baseosc*measure_horizontal()/horzbase;
  354.     }
  355.  
  356.     cpu_regs.h.ah = 0x00;
  357.     cpu_regs.h.al = 0x03;
  358.     int86(0x10, &cpu_regs, &cpu_regs);
  359.  
  360.     printf2("\n#define CLOCK_VALUES {\t\\\n");
  361.     for (i = 0; i < 8; ++i)
  362.       printf2("\t/* %d */ %5.0f%s\t\\\n", i, clock[i],(i==7?"":","));
  363.     printf2("\t}\n");
  364. }
  365.  
  366. void one_mode(int vesa_mode, int mode, int colbits, int funny_card)
  367. {
  368.     union REGS cpu_regs;
  369.     int i, skip = 0, modeok = 0;
  370.     int x=0, y, col, size;
  371.     char resol[100], colors[100], *desc;
  372.     char   *verttxt;
  373.     double vertical, horizontal;
  374.  
  375.     switch (mode) {
  376.     case 0x13: x =  320; y =  200; break;
  377.     case 0x25: x =  640; y =  480; break;
  378.     case 0x29: x =  800; y =  600; break;
  379.     case 0x2d: x =  640; y =  350; break;
  380.     case 0x2e: x =  640; y =  480; break;
  381.     case 0x2f: x =  640; y =  400; break;
  382.     case 0x30: x =  800; y =  600; break;
  383.     case 0x37: x = 1024; y =  768; break;
  384.     case 0x38: x = 1024; y =  768; break;
  385.     case 0x3d: x = 1280; y = 1024; break;
  386.     default  : switch (vesa_mode) {
  387.              case 0x107:
  388.              case 0x119:
  389.              case 0x11a:
  390.              case 0x11b: x = 1280; y = 1024; break;
  391.              default   : return;
  392.            }
  393.            break;
  394.     }
  395.     col = (1<<colbits);
  396.     size = (int)((((unsigned long) x) * ((unsigned long) y)) >> 10);
  397.     if (col == 16) size >>= 2;
  398.  
  399.     switch (colbits) {
  400.     case 15: size*=2; strcpy(colors, "32K"); desc = "HiColor ";   break;
  401.     case 16: size*=2; strcpy(colors, "64K"); desc = "HiColor ";   break;
  402.     case 24: size*=3; strcpy(colors, "16M"); desc = "TrueColor "; break;
  403.     default: sprintf(colors, "%d", col); desc = ""; break;
  404.     }
  405.     sprintf(resol, "%dx%dx%s", x, y, colors);
  406.  
  407.     if (!do_all) {
  408.       char expl[100];
  409.       sprintf(expl, "BIOS mode 0x%2X : %s", mode, resol);
  410.       switch(ask(expl)) {
  411.     case ASK_SKIP : skip = 1; break;
  412.     case ASK_ALL  : do_all = 1; break;
  413.     default       : break;
  414.       }
  415.     }
  416.  
  417.     if (!skip) {
  418.       /* First try VESA mode */
  419.       if (vesa_mode != 0) {
  420.     cpu_regs.x.ax = 0x4f02;
  421.     cpu_regs.x.bx = vesa_mode;
  422.     int86(0x10, &cpu_regs, &cpu_regs);
  423.     modeok = (cpu_regs.x.ax == 0x004f);
  424.       }
  425.       /* Try std ET4000 mode numbers if VESA failed */
  426.       if (!modeok && mode != 0) {
  427.     switch (colbits)
  428.     {
  429.         case 15:
  430.         case 16:
  431.         cpu_regs.x.ax=0x10F0;
  432.         cpu_regs.h.bl=mode;
  433.         break;
  434.         case 24:
  435.         switch (funny_card)
  436.         {
  437.             case 1:
  438.             cpu_regs.x.ax=0x10E0;
  439.             cpu_regs.h.bl=0x2e;
  440.             break;
  441.             case 2:
  442.             cpu_regs.x.ax=0x10f0;
  443.             cpu_regs.h.bl=0x3e;
  444.             break;
  445.             case 0:
  446.             default:
  447.             cpu_regs.x.ax=0x10F0;
  448.             cpu_regs.h.bh=mode;
  449.             cpu_regs.h.bl=0xFF;
  450.             break;
  451.         }
  452.         break;
  453.         case 0:
  454.         default:
  455.         cpu_regs.h.ah = 0x00;
  456.         cpu_regs.h.al = mode;
  457.         break;
  458.     }
  459.  
  460.     int86(0x10, &cpu_regs, &cpu_regs);
  461.     modeok = !(  (colbits > 8 && cpu_regs.x.ax != 0x0010)
  462.            ||(colbits <=8 && cpu_regs.x.ax == mode  ) );
  463.     vesa_mode = 0;
  464.       }
  465.  
  466.       if (modeok) {
  467.     /* get VGA register values */
  468.     for (i = 0; i < CRT_C; i++) {
  469.         port_out(i, CRT_I);
  470.         vga_regs[CRT+i] = port_in(CRT_D);
  471.     }
  472.     for (i = 0; i < ATT_C; i++) {
  473.         if (col == 16 && i < 16)
  474.           vga_regs[ATT+i] = i;
  475.         else {
  476.           port_in(IS1_R);
  477.           port_out(i, ATT_IW);
  478.           vga_regs[ATT+i] = port_in(ATT_R);
  479.         }
  480.     }
  481.     for (i = 0; i < GRA_C; i++) {
  482.         if (i==1 && col == 16)
  483.           vga_regs[GRA+i] = 0x0F;
  484.         else {
  485.           port_out(i, GRA_I);
  486.           vga_regs[GRA+i] = port_in(GRA_D);
  487.         }
  488.     }
  489.     for (i = 0; i < SEQ_C; i++) {
  490.         port_out(i, SEQ_I);
  491.         vga_regs[SEQ+i] = port_in(SEQ_D);
  492.     }
  493.     vga_regs[MIS] = port_in(MIS_R);
  494.  
  495.     /* get extended CRT registers */
  496.     for (i = 0; i < 8; i++) {
  497.          port_out(0x30+i, CRT_I);
  498.          vga_regs[EXT+i] = port_in(CRT_D);
  499.     }
  500.     port_out(0x3f    , CRT_I);
  501.     vga_regs[EXT+8] = port_in(CRT_D);
  502.  
  503.     /* get extended sequencer register */
  504.     port_out(7, SEQ_I);
  505.     vga_regs[EXT+9] = port_in(SEQ_D);
  506.  
  507.     /* get some other ET4000 specific registers */
  508.     vga_regs[EXT+10] = port_in(0x3c3);
  509.     vga_regs[EXT+11] = port_in(0x3cd);
  510.  
  511.     /* get extended attribute register */
  512.     port_in(IS1_R);   /* reset flip flop */
  513.     port_out(0x16, ATT_IW);
  514.     vga_regs[EXT+12] = port_in(ATT_R);
  515.  
  516.     if (save_extregs) {       /* copy stg170x extended info */
  517.         vga_regs[EXT+13] = read_dac(0);
  518.         write_dac(0,vga_regs[EXT+13] | 0x10);
  519.         vga_regs[EXT+14] = read_ext_dac(3);
  520.         vga_regs[EXT+15] = read_ext_dac(4);
  521.         vga_regs[EXT+16] = read_ext_dac(5);
  522.     }
  523.  
  524.     /* Measure video timing */
  525.     horizontal = measure_horizontal();
  526.     /* switch back to text mode */
  527.     cpu_regs.h.ah = 0x00;
  528.     cpu_regs.h.al = 0x03;
  529.     int86(0x10, &cpu_regs, &cpu_regs);
  530.       }
  531.     }
  532.  
  533.     if (vesa_mode)
  534.       printf2("\n/* VESA %smode 0x%03X", desc, vesa_mode);
  535.     else
  536.       printf2("\n/* ET4000 %sBIOS mode 0x%02X", desc, mode);
  537.     printf2(" -- %s", resol);
  538.     if ( skip || !modeok) {
  539.     printf2(" : NOT SUPPORTED */\n");
  540.     if (size <= 1024)
  541.       printf2("#define g%s_regs DISABLE_MODE\n", resol);
  542.     return;
  543.     }
  544.     printf2(" */\n");
  545.  
  546.     /* can't always treat 15 and 16 bit modes the same! */
  547.     if (colbits == 16 && !save_extregs) {
  548.       printf2("#define g%s_regs g%dx%dx32K_regs\n", resol, x, y);
  549.       return;
  550.     }
  551.  
  552.     verttxt = interlaced() ? " (interlaced)" : "";
  553.     vertical   = horizontal / calc_vtotal();
  554.     printf2("/* Video timing:\tVertical frequency   : %4.1fHz%s\n",
  555.                         vertical, verttxt);
  556.     printf2("\t\t\tHorizontal frequency : %4.1fKHz  */\n", horizontal/1000.0);
  557.     printf2("static unsigned char g%s_regs[%d] = {\n  ", resol, TOTAL);
  558.     for (i = 0; i < CRT_C; i++)
  559.     printf2("%s0x%02X,", (i==12?"\n  ":""), vga_regs[CRT+i]);
  560.     printf2("\n  ");
  561.     for (i = 0; i < ATT_C; i++)
  562.     printf2("%s0x%02X,", (i==12?"\n  ":""), vga_regs[ATT+i]);
  563.     printf2("\n  ");
  564.     for (i = 0; i < GRA_C; i++)
  565.     printf2("0x%02X,",vga_regs[GRA+i]);
  566.     printf2("\n  ");
  567.     for (i = 0; i < SEQ_C; i++)
  568.     printf2("0x%02X,",vga_regs[SEQ+i]);
  569.     printf2("\n  0x%02X,",vga_regs[MIS]);
  570.     printf2("\n  0x%02X",vga_regs[EXT]);
  571.     for (i = 1; i < EXT_C; i++)
  572.     printf2(",%s0x%02X", (i==12?"\n  ":""), vga_regs[i+EXT]);
  573.     printf2("\n};\n");
  574. }
  575.  
  576. void usage(void) {
  577.   cputs("tseng3 <output_file> [SS24]");
  578.   exit(1);
  579. }
  580.  
  581. void main(int argc, char* argv[])
  582. {
  583.     int funny_card = 0;
  584.  
  585.     if (argc >= 2)
  586.       output = fopen(argv[1], "w");
  587.  
  588.     if (output != NULL)
  589.       fputs("/*\n   ( File generated by tseng3.exe )\n\n", output);
  590.     puts2("tseng3 v1.2, Copyright (C) 1993  Tommy Frandsen, Harm Hanemaayer");
  591.     puts2("and Hartmut Schirmer\n");
  592.     puts2("Permission is granted to any individual or institution to use, copy, or");
  593.     puts2("redistribute this executable so long as it is not modified and that it is");
  594.     puts2("not sold for profit.\n");
  595.     puts2("LIKE ANYTHING ELSE THAT'S FREE, TSENG3 IS PROVIDED AS IS AND COMES WITH");
  596.     puts2("NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL");
  597.     puts2("THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF");
  598.     puts2("THIS SOFTWARE.");
  599.     if (output != NULL)
  600.       fputs("*/\n", output);
  601.     puts2("");
  602.  
  603.     if (argc >= 2 && output == NULL)
  604.     usage();
  605.  
  606.     if (argc>=3)
  607.     funny_card = (strcmp("SS24", argv[2]) == 0) ? 1 : 2;
  608.  
  609.     get_dac();
  610.     get_clocks();
  611.  
  612.     one_mode(0x10d, 0x13, 15, funny_card);  /* 320x200x32K */
  613.     one_mode(0x10e, 0x13, 16, funny_card);  /* 320x200x64K */
  614.     one_mode(0x10f, 0x13, 24, funny_card);  /* 320x200x16M */
  615.     one_mode(0x101, 0x2e,  8, funny_card);  /* 640x480x256 */
  616.     one_mode(0x110, 0x2e, 15, funny_card);  /* 640x480x32K */
  617.     one_mode(0x111, 0x2e, 16, funny_card);  /* 640x480x64K */
  618.     one_mode(0x112, 0x2e, 24, funny_card);  /* 640x480x16M */
  619.     one_mode(0x102, 0x29,  4, funny_card);  /* 800x600x16 */
  620.     one_mode(0x103, 0x30,  8, funny_card);  /* 800x600x256 */
  621.     one_mode(0x113, 0x30, 15, funny_card);  /* 800x600x32K */
  622.     one_mode(0x114, 0x30, 16, funny_card);  /* 800x600x64K */
  623.     one_mode(0x115, 0x30, 24, funny_card);  /* 800x600x16M */
  624.     one_mode(0x104, 0x37,  4, funny_card);  /* 1024x768x16 */
  625.     one_mode(0x105, 0x38,  8, funny_card);  /* 1024x768x256 */
  626.     one_mode(0x116, 0x38, 15, funny_card);  /* 1024x768x32K */
  627.     one_mode(0x117, 0x38, 16, funny_card);  /* 1024x768x64K */
  628.     one_mode(0x118, 0x38, 24, funny_card);  /* 1024x768x16M */
  629.     one_mode(0x106, 0x3D,  4, funny_card);  /* 1280x1024x16 */
  630.     one_mode(0x107, 0x00,  8, funny_card);  /* 1280x1024x256 */
  631.     one_mode(0x119, 0x00, 15, funny_card);  /* 1280x1024x32K */
  632.     one_mode(0x11a, 0x00, 16, funny_card);  /* 1280x1024x64K */
  633.     one_mode(0x11b, 0x00, 24, funny_card);  /* 1280x1024x16M */
  634.     puts2("\n/* --- ET4000 specific modes */\n#ifdef _DYNAMIC_ONLY_");
  635.     one_mode(0x000, 0x2d,  8, funny_card);  /* 640x350x256 */
  636.     one_mode(0x000, 0x2d, 15, funny_card);  /* 640x350x32K */
  637.     one_mode(0x000, 0x2d, 16, funny_card);  /* 640x350x64K */
  638.     one_mode(0x000, 0x2d, 24, funny_card);  /* 640x350x16M */
  639.     one_mode(0x100, 0x2f,  8, funny_card);  /* 640x400x256 */
  640.     one_mode(0x000, 0x2f, 15, funny_card);  /* 640x400x32K */
  641.     one_mode(0x000, 0x2f, 16, funny_card);  /* 640x400x64K */
  642.     one_mode(0x000, 0x2f, 24, funny_card);  /* 640x400x16M */
  643.     puts2("\n#endif /* defined(_DYNAMIC_ONLY_ALL_) */\n");
  644. }
  645.  
  646.